home *** CD-ROM | disk | FTP | other *** search
Text File | 1987-03-08 | 39.4 KB | 1,005 lines |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- U P L
-
- User Processing Language
- for Fido and Opus Sysops
-
-
- Version 1.00 -- 3-8-87
-
-
-
-
-
-
-
-
-
-
-
-
-
- By Rick Huebner
- FidoNet/Matrix node 14/614
- 402-291-8053, 3/12/2400 bps, 24 hrs.
-
-
- Copyright 1987 Rick Huebner
- (Released for non-commercial use and distribution)
-
-
-
-
-
-
-
- Table of Contents
- -----------------
-
- 0.0 Legal notices and other crud to get over with ASAP
- 0.1 Distribution Rights.
- 0.2 Warranty.
- 0.3 Social Commentary.
-
- 1.0 Overview/Introduction
- 1.1 What it is (bro').
- 1.2 Warnings, caveats, CYA.
- 1.3 Theory of Operation.
-
- 2.0 Language Syntax
- 2.1 Invocation.
- 2.2 Command File Format.
-
- 3.0 Language Components
- 3.1 Constants.
- 3.2 Variables.
- 3.3 Expressions.
- 3.4 Commands.
-
- 4.0 Programming Considerations
- 4.1 Limitations.
- 4.2 Efficiency considerations.
-
- 5.0 Postscript
- 5.1 Future Enhancements.
- 5.2 Bug Reports, etc.
-
-
-
-
- 0.0 Legal notices and other crud to get over with ASAP
- --------------------------------------------------------
-
- 0.1 Distribution Rights.
-
- You are hereby granted a limited license to use UPL in any way you see fit,
- and to distribute it in any way you wish, so long as you don't charge more than
- $5 for it, said money intended to defray distribution costs. If I catch you
- selling my software for profit, I'll say very nasty things about you on every
- network I have access to, attempt to start a boycott, and generally be as
- snotty about it as I can. And if you're actually making any real money from
- this, I'll sue you for every penney of it. So there.
-
- Also, I'd like to ask that patched or modified copies of this program not be
- distributed. That's why I'm not giving out the source code... I hate it when
- 97 parallell versions of a popular program hit the phone lines. I wouldn't
- want that to happen to UPL, if it were to become popular, so I'm going to
- maintain central control of the code. Besides, this saves me the trouble of
- properly commenting my software.
-
-
- 0.2 Warranty.
-
- There isn't one. This is a gift, not a commercial product; you have no
- legal recourse whatsoever. If it doesn't work, tough. If it makes your hard
- disk into a neutron bomb, tough (although I would appreciate being informed).
- Now that that's out of the way, I'll promise that I did test this stuff pretty
- thoroughly before sending it out with my name on it, and that it works great
- for me. But you know as well as I do that no program of this complexity is
- ever really bug-free, especially on version 1.00. All I can do is try to fix
- 'em as I'm told about 'em, so please tell me about 'em. For your own safety,
- back up your USER.BBS file and test all programs before installing them
- operationally. Lead shielding is optional.
-
-
- 0.3 Social Commentary.
-
- This program is a contribution on my part to the Fido/Opus community. It's
- my way of paying back a little of the work of all those other utility writers
- whose programs make this such an enjoyable hobby. In my humble (and totally
- unsolicited) opinion, if more people remembered their debt to the public domain
- and reimbursed it in kind, we'd all have a lot more fun. Do Shareware authors
- generally make enough money to pay the Shareware fees for the software which
- they themselves use? Can you say "vicious circle?" I thought you could.
-
-
-
-
- 1.0 Overview/Introduction
- ---------------------------
-
- 1.1 What it is (bro').
-
- UPL (User Processing Language) is an interpreted language specifically
- designed to help Fido and Opus sysops maintain their USER.BBS user data files.
- With it, you can do almost anything that you might ever want to your user data.
- You can change any piece of data for any user or group of users, generate all
- kinds of reports, automatically upgrade or downgrade user privileges according
- to your own wierd criteria, generate Opus custom welcome messages, and more.
- You want to purge all users who've called a prime number of times, use nulls,
- and have dared to look into message area 2? No sweat. On a more practical
- side, you want to automatically upgrade the privs of good upload contributors?
- Or generate nastygrams to download leeches? Or fix people's message read
- counters after you've rearranged your message areas? Also no sweat.
-
-
- UPL features:
-
- * Predefined variables for access to every part of a Fido or Opus USER.BBS
- data record
-
- * Special variables for things like upload/download ratio, number of days
- since last call, command line arguments, etc.
-
- * Predefined constants for standard privilege levels, help levels, etc.
-
- * User-defined variables (for loop counters, doing computations, etc.)
-
- * 4-function math operations (ADD, SUB, MUL, DIV, MOD, no etc.)
-
- * Nested IF-THEN-ELSE blocks
-
- * GOTOs and labels
-
- * Full trace mode for debugging
-
- * 'Intelligent' support of Opus's .GBS/.BBS files and custom welcomes
-
- * Lots more. Really.
-
-
- 1.2 Warnings, caveats, CYA.
-
- UPL's strengths are flexibility and convenience. You can do almost anything
- with it, but you obviously (or hopefully) won't be able to do it as well as
- with a special-purpose utility. Also, like any programming language, you need
- a bit of programming skill to use it properly. UPL will happily trash your
- entire user file beyond recognition if you ask it to. In the interest of speed
- and efficiency, >>> UPL DOES NOT CREATE A BACKUP FILE <<< (except when purging
- deleted users). Once again, thoroughly test all new programs on a backup copy
- of USER.BBS before installation. Don't say I didn't warn you.
-
-
-
-
- 1.3 Theory of Operation.
-
- A UPL program is a sequence of UPL commands which is executed against each
- record in your USER.BBS file. In other words, all UPL programs are considerd
- to be inside a loop which says:
-
- FOR USERNUM=0 TO LASTUSER
- <<< Your program >>>
- NEXT USERNUM
-
- There are special commands provided which allow you to branch around within
- your program, proceed to the next user, proceed to the next program, abort
- everything, chain to another command file, etc. There are commands provided to
- let you test or set any of the data in a user's record, perform simple
- calculations, and print output to the screen or to a file. There's even a DOS
- shell command to let you run other utilities from within a UPL program.
-
- The simplest UPL program would be something like:
-
- SET @FILEAREA 1
-
- which simply sets every user's 'last file area accessed' pointer to 1. This is
- handy when you've rearranged your file areas (again) and don't want any of your
- users to pop out into hyperspace when they go to the file section. A slightly
- more complex program could be like:
-
- IfGT @Downloads 1000
- IfLT @ULRatio 5
- Print '@name is a leech:'
- Print ' Uploads=@uploadsKB, Downloads=@downloadsKB, Ratio=@ulratio%'
- Set @Priv @Disgraced
- Else
- IfGT @ULRatio 25
- Print '@name is wonderful.'
- Set @Priv @Privil
- EndIf
- EndIf
- EndIf
-
- which would set any users who've downloaded more than a megabyte (1000K) and
- uploaded less than 5% to Disgraced, and anyone who's uploaded more than 25% to
- Privil. Other example programs were (hopefully) included with the software,
- and you've probably already looked at them by now, so you should be getting the
- idea.
-
-
-
-
- 2.0 Language Syntax
- ---------------------
-
- 2.1 Invocation.
-
- You execute a UPL program with the following command:
-
- UPL[/[B][+][$][#]] commandfile [argument1..argument9]
-
- 'commandfile' is the name of a plain ASCII text file which contains UPL
- commands to be executed. If no period is found in the name, the suffix '.UPL'
- will be assumed. If the file is not in the current directory, your PATH will
- be searched for it.
-
- '[argument1..argument9]' represents up to 9 command line arguments which may
- be passed to the UPL program. Blanks and tabs are delimiters. If you wish an
- argument to contain embedded blanks or tabs, the argument must be delimited
- with single or double quotation marks. To specify a null argument, use "".
- Arguments which are not given will be considered null ("") if referenced by the
- UPL program. All arguments are shifted to upper-case before use.
-
- 'B', '+', '$', and '#' are flags. They may be specified in any combination
- or sequence, such as 'UPL/B#+$' or 'UPL/$#'. Each flag enables a particular
- function, as follows:
-
- 'B' enables Batch mode. If this flag is not specified, any fatal errors
- encountered while running your program will cause UPL to print a text
- error message and pause for your acknowledgement. If Batch mode is
- specified, UPL will print an error number and die without waiting for
- operator input. This allows UPL to be run more safely from unattended
- batch files. Upper and lower case are both accepted.
-
- '+' enables user record number trace mode. This will cause UPL to print
- a trace message as it processes each user record. This lets you see
- UPL's progress through your user data file.
-
- '$' enables source file trace mode. This will cause UPL to display each
- line of source code from the command file as it is executed. This
- allows you to trace the execution of your command files.
-
- '#' enables expression trace mode. This will cause UPL to display each
- command which accepts arguments AFTER the arguments have been
- completely evaluated. This is useful when debugging programs which
- use complex expressions.
-
-
-
-
- 2.2 Command File Format.
-
- 2.2.1 Statements.
-
- UPL commands are entered one per line. Commands may have up to two
- arguments. Spaces and tabs are used as delimiters. If embedded spaces or tabs
- are required within an argument, the argument must be delimited with single or
- double quotation marks. To include quotation marks within an argument, you
- must delimit it with the other kind of quotes. Each command has a fixed number
- of arguments; any extra arguments on the line are completely ignored. This
- allows inline comments to follow the command. If an insufficient number of
- arguments are specified, the missing arguments will be considered null ("").
- Leading spaces and tabs are ignored, allowing you to indent as desired. Upper
- and lower case may be mixed freely.
-
- 2.2.2 Labels.
-
- A label may be any string expression whose rightmost character is ":". It
- must be the first expression on the line. Upper and lower case are not
- significant, as all labels are shifted to upper-case before parsing. Any extra
- arguments after the label are treated as comments and ignored. A label may be
- any number of characters, and can even have blanks and tabs in it if you feel
- like using quotes. It's your program; I don't have to be able to read it.
-
- 2.2.3 Comments, blank lines, etc.
-
- Any text after the expected number of arguments for a command is treated as
- a comment and ignored. Lines which contain only blanks and tabs, or which
- contain nothing at all, are ignored. Any line whose first non-blank-non-tab
- character is also non-alphabetic ('A'-'Z' or 'a'-'z'), is also considered a
- comment and ignored. If you have source code trace mode on ('/$'), the entire
- source code line will be displayed verbatim as it is executed. This allows you
- to place inline comments on your commands and see those comments in your trace
- output.
-
- 2.2.4 Multiple programs per command file.
-
- A single command file may contain any number of programs. Each program will
- be executed in sequence until the end of file is encountered. Each program is
- separated from the next by the RUN command. User variables are carried over
- from one program to the next; in all other respects, each program acts as if it
- were the only one in the file. Most especially, labels are only recognized
- within the program they are defined in. In other words, you can't GOTO one
- program from another. In order to change from one program to another you must
- proceed through the command file to that point, or use the CHAIN command to
- invoke another command file. You can also use the CHAIN command to re-invoke
- the current command file, but you'd better have code in place which decides to
- quit doing this eventually (unless you're fond of infinite loops).
-
-
-
-
- 3.0 Language Components
- -------------------------
-
- 3.1 Constants.
-
- A constant is the most basic part of an expression. It is either some text
- which you've entered yourself, or a predefined value such as @TWIT, or any
- combination of the two. The following predefined constants are available:
-
- Privilege Levels: Help Levels: Command Line Arguments:
- @TWIT -2 @EXPERT 2 @ARG0 through @ARG9
- @DISGRACED 0 @REGULAR 4
- @NORMAL 2 @NOVICE 6
- @PRIVIL 4
- @PRIVEL 4 Miscellaneous:
- @EXTRA 6 @OFF 0
- @ASSTSYSOP 8 @ON 1
- @SYSOP 10 @DATE current date
- @HIDDEN 11 @TIME current time
-
- When UPL is evaluating an expression, it simply substitutes the proper value
- in place of any predefined constants it encounters. @ARG0 will always be the
- name of the currently executing command file; the other @ARG values will be as
- given when UPL was run.
-
-
-
- 3.2 Variables.
-
- A variable is like a constant, except that its value changes from one user
- record to the next. Variables may also be changed by your program, and the
- user data file will be updated accordingly. There are also 10 scratchpad
- variables available for your own use; they don't have any relation to the user
- data, but are instead used for loop counting, doing math, etc. The following
- variables are available:
-
- USER.BBS User Data Record:
- @NAME String User's first and last names
- @CITY String City and state
- @DELFLG2 Bit Marks deleted records for REMSYSOP
- @MRA0 - @MRA9 Integer Last Message Read Area numbers
- @MRC0 - @MRC9 Integer Last Message Read message counters
- @PASSWORD String User's password (aka PWD)
- @CALLS Integer Number of times user has called (aka TIMES)
- @HELP Integer User's current help setting
- @TABS Integer 0=translate tabs to spaces on output
- @NULLS Integer Number of nulls to send after CR
- @MSGAREA Integer Last message area visited (aka MSG)
- @MOREWORD Integer Word containing various flag bits
- @MOREBIT0 thru Bit Individual bits in MOREWORD; Bit 0=least
- @MOREBITF sig. (1), Bit F=most sig. (32768)
- @MORE Bit Set = Use MORE? prompts (@FLAGBITF)
- @ANSI Bit Set = Use ANSI graphics (@FLAGBITE)
- @KLUDGE Bit Set = Been on Opus before (@FLAGBITD)
- @FORMFEED Bit Set = Perform screen clears (@FLAGBITC)
- @PRIV Integer User's privilege level
- @LASTCALL String Date and time of last call (aka LDATE)
- @OLTODAY Integer Time online so far today (aka TIME)
- @FLAGWORD Integer Word containing various bit flags
- @FLAGBIT0 thru Bit Individual bits in FLAGWORD; Bit 0=least
- @FLAGBITF sig. (1), Bit F=most sig. (32768)
- @DELFLG1 Bit Marks deleted records for SYSOP207 & others
- @UPLOADS Unsigned Total KB uploaded by this user (aka UPLD)
- @DOWNLOADS Unsigned Total KB downloaded by this user (DNLD)
- @DLTODAY Integer (downloads-uploads) performed today (DNLDL)
- @FILEAREA Integer Last file area visited (aka FILES)
- @WIDTH Byte Width of user's screen
- @LENGTH Byte Length of user's screen
- @CREDIT Integer Netmail message credit, in cents
- @DEBIT Integer Pending netmail message debt, in cents
-
- Variables Derived from the User Record (can't be changed directly):
- @DAYSAGO Integer Number of days since last call
- @ULRATIO Unsigned UPLOADS/DOWNLOADS, given as a percentage
- @USERNUM Integer User record number being processed (from 0)
-
- Variables for you to play with:
- @VAR0 - @VAR9 String Use for whatever you want
-
- Variables have a specific data type (String, Integer, etc.). UPL will
- attempt to convert data as neccessary in order to perform your commands, but
- some operations (like SET @UPLOADS "FROG") are obviously impossible and will
- get you a fatal error. When setting Bit variables, any non-zero value will be
- treated as 1. When setting Byte variables, only the least-significant byte of
- the new value will be used. Note that the scratchpad variables are described
- as Strings. They may contain whatever you want, and UPL will attempt to figure
- them out by context.
-
-
-
-
- 3.3 Expressions.
-
- An expression is any combination of literal text, constants, and variables.
- UPL will substitute the proper values for any constants or variables found
- before using an expression. Substitutions are made iteratively from left to
- right until no more constants or variables can be found. For example:
-
- "@name is a great guy." might equal "Rick Huebner is a great guy."
- "SET @PRIV @TWIT" would be executed as "SET @PRIV -2"
-
- but here's a better one:
-
- SET @VAR0 9
- SET @VAR3 "TEXT STRING"
- SET @VAR9 3
- PRINT Complex@VAR@VAR@VAR0Expression
-
- would print: "ComplexTEXT STRINGExpression" because "@VAR@VAR@VAR0" would be
- translated first into "@VAR@VAR9", and then into "@VAR3", and finally into
- "TEXT STRING". Note that the "@" is only significant if it directly precedes a
- recognizable variable or constant name; otherwise, it's just text. Also,
- remember that labels are just another kind of string; you can do some really
- neat things with commands like "GOTO Case@VAR0" if you program it properly.
- This is left as an exercise for the reader.
-
- There are two special-purpose kinds of expressions used by certain UPL
- commands: Filename and Textline. If a Filename expression does not contain a
- period, an extension of ".GBS" or ".BBS" will be assumed, according to the
- user's @ANSI setting and which files exist. The selection logic is like this:
-
- If user's ANSI setting is off then
- Append ".BBS" to filename
- Else
- If filename.GBS does not exist and filename.BBS does exist,
- Append ".BBS" to filename
- Else
- Append ".GBS" to filename
- EndIf
- EndIf
-
- This allows you to write to or copy from files which properly correspond to
- the user's ANSI setting. Note that since the ANSI bit should never be set on a
- Fido board, Fido sysops may consider Filename expressions to simply have a
- default extension of ".BBS".
-
- The other kind of special-purpose expression is the Textline. The PRINT and
- FPRINT commands use this expression type. It's simply a generic string
- expression with 2 extra format commands recognized. Any occurrance of "$nn",
- where "nn" is a valid 2-character hexadecimal number, will be replaced by a
- byte with that ASCII value. Also, if the string ends with a semicolon (;), the
- carriage-return at the end of the string will be suppressed. If you wish the
- semicolon at the end of the line to print out, use "Text; ". If you wish to
- both print a semicolon at the end AND suppress the carriage-return, use
- "Text;;". Got all that?
-
-
-
-
- 3.4 Commands.
-
- 3.4.1 ABORT
-
- Causes UPL to stop processing immediately and return to DOS. This command
- differs from END in that the entire command file is aborted, not just the
- currently executing program.
-
- See also: CHAIN, END, NEXTUSER, RUN
-
-
- 3.4.2 ADD variable numerical_expression
-
- Adds the value of 'numerical_expression' to 'variable'. If
- 'numerical_expression' is null (""), its value is considered to be 0, and
- nothing happens.
-
- Examples: ADD @VAR0 1
- ADD @CREDIT @ARG2
-
- See also: SUB, MUL, DIV, MOD, SET
-
-
- 3.4.3 CHAIN string_expression
-
- Transfers control to the command file named in 'string_expression'. Control
- will not return to the current command file. 'string_expression' has exactly
- the same format as the DOS command line.
-
- Examples: CHAIN "/$ othrfile argone 'arg two' arg3"
- CHAIN "@Arg0 @Arg1 NewArg2 @Arg3"
-
- See also: ABORT, END, NEXTUSER, RUN
-
-
- 3.4.4 CWKILL
-
- Deletes all Opus custom welcome messages from the current directory. A
- custom welcome message is defined as "n.BBS", where 'n' is any valid decimal
- integer value. This is used to delete outdated messages before creating new
- ones. It's a good idea to immediately follow this command with END, since it's
- silly (and slow) to delete all the old messages once for every user in your
- user list.
-
- See also: DOS, FAPPEND, FPRINT, MQFLUSH, MQMSG
-
-
- 3.4.5 DIV variable numerical_expression
-
- Divides the value in 'variable' by the value of 'numerical_expression'.
- If 'numerical_expression' is 0 or null ("") a fatal error will occur. The
- result will have any fractional part truncated. Use MOD to determine the
- remainder if neccessary.
-
- Examples: DIV @VAR0 10
-
- See also: ADD, SUB, MUL, MOD, SET
-
-
-
-
- 3.4.6 DOS string_expression
-
- Bring up a child copy of COMMAND.COM to execute the command in
- 'string_expression'. If 'string_expression' is null ("") or missing (same
- thing), the new COMMAND.COM will wait for you to type in commands at your
- keyboard, and control will not pass back to UPL until you type the "EXIT"
- command. This command requires a lot of memory, the exact amout depending on
- just what you try to run.
-
- Examples: DOS
- DOS "renum -n 0 150 @VAR0 -r @VAR0"
-
- See also: CWKILL, FAPPEND, FPRINT, MQFLUSH, MQMSG
-
-
- 3.4.7 END
-
- Halts the execution of the current program, and causes UPL to continue
- forward to the next program in the command file (if any). UPL pretends like it
- has all of a sudden finished processing the last user in your data file.
-
- See also: ABORT, CHAIN, NEXTUSER, RUN
-
-
- 3.4.8 FAPPEND filename_expression1 filename_expression2
-
- Copies the contents of the file named by 'filename_expression2' onto the end
- of the file named by 'filename_expression1'. The file named by
- 'filename_expression2' must already exist or a fatal error will occur. If the
- file named by 'filename_expression1' does not exist, it is created. If a
- filename extension is not present, '.GBS' or '.BBS' will be assumed as
- appropriate. See section 3.3 for details.
-
- Examples: FAPPEND @usernum.bbs twit (copies TWIT.<G B>BS to the user's
- custom welcome message file)
-
- See also: CWKILL, DOS, FPRINT, MQFLUSH, MQMSG
-
-
- 3.4.9 FPRINT filename_expression textline_expression
-
- Appends the text in 'textline_expression' to the end of the file named by
- 'filename_expression'. If the file named by 'filename_expression' does not
- already exist, is is created. See section 3.3 for details on filename and
- textline expressions.
-
- Examples: FPRINT purge.rpt @name$09@lastcall$09@daysago
- FPRINT @usernum.bbs "$0FCc:\opus\misc\hell"
-
- See also: CWKILL, DOS, FAPPEND, MQFLUSH, MQMSG
-
-
-
-
- 3.4.10 GOTO label_expression
-
- Jumps to the next command line after the line which contains
- 'label_expression'. The colon (":") on the end of the label should not be
- given in the GOTO command. See section 2.2.2 for label syntax details.
-
- Examples: GOTO TopOfLoop
- GOTO Priv@PRIV (will jump to 'Priv-2', 'Priv0', 'Priv2', etc.)
- GOTO Case@VAR0
-
- See also: IF
-
-
- 3.4.11 IF
-
- Compares two expressions to each other, and decides where to go based on the
- results. The full structure is:
-
- IFxx expression1 expression2
- <<< other commands >>>
- [ELSE]
- [ <<< other commands>>> ]
- ENDIF
-
- 'xx' may be any one of 'EQ', 'NE', 'LT', 'LE', 'GT', or 'GE'. If the condition
- is true, the first set of commands will be executed. If the condition is
- false, the second set of commands will be executed (if present). The two
- expressions to be compared may be of any type. If both expressions can be
- converted to a 16-bit integer, the comparison will be made arithmetically; if
- one or the other expression is not numeric, the comparison will be made
- alphabetically. The comparison is performed in upper-case, so the case of the
- two expressions is not significant. Comparison with unsigned variables
- (@UPLOADS, @DOWNLOADS, @ULRATIO) is a special case; the values will be
- converted to 5-digit 0-padded strings and compared alphabetically, so as to
- avoid problems like 60000 being less than 1. Also, if @DOWNLOADS equals 0,
- @ULRATIO will equal 65535, which is as close to infinity as you can get in 16
- bits. If you have expression trace mode ("/#") on, you can tell whether the
- comparison is being made arithmetically or alphabetically by looking for
- quotation marks around the expressions.
-
- Examples: Ifeq @name 'rick huebner'
- set @priv @extra
- endif
-
- IfLT @var0 @var1 Then ('Then' is a comment, but it looks good)
- Print "@var0 is less than @var1."
- Else
- Print "@var0 is not less than @var1."
- Endif
-
- See also: GOTO
-
-
-
- 3.4.12 MOD variable numerical_expression
-
- Sets 'variable' equal to the remainder of 'variable' divided by
- 'numerical_expression.' For example, if 'variable' contained 10, and
- 'numerical_expression' worked out to 3, 'variable' would end up being set to 1
- (10 mod 3 = 1). If 'numerical_expression' is 0 or null ("") a fatal error will
- occur.
-
- Examples: MOD @VAR0 10
-
- See also: ADD, SUB, MUL, DIV, SET
-
-
- 3.4.13 MQFLUSH
-
- This is a special-purpose command designed to work with MQMSG. It clears
- the flag which MQMSG uses to tell if it has already run POLE_MQ or not, forcing
- MQMSG to re-execute POLE_MQ on the next iteration. Frankly, I'm not sure if
- there's a good application for this or not, but I threw it in for completeness'
- sake. See the description of MQMSG below for details.
-
- See also: CWKILL, DOS, FAPPEND, FPRINT, MQMSG
-
-
- 3.4.14 MQMSG string_expression
-
- This is a very special-purpose command. It executes POLE_MQ with the
- arguments given in 'string_expression', loads the output report into memory,
- and then creates/appends to an Opus custom welcome message those lines showing
- that individual user's waiting mail. This way, each user gets a quick one or
- two line message showing only their waiting messages, rather than everybody
- having to read a full-page report showing everybody's waiting messages. POLE_MQ
- is only actually run on the first use of this command; after that, the output
- file has been loaded into memory and is simply scanned for each user. Use the
- MQFLUSH command if you wish to force POLE_MQ to be run again once it has
- executed. If the current user was not reported to have waiting mail by
- POLE_MQ, this command does nothing. POLE_MQ must be able to be found via your
- DOS PATH for this command to work. Also, like any command which runs a second
- program, it requires a lot of memory.
-
- The special reserved variable @MAIL is set by this command to reflect the
- number of lines of text which were appended to the user's custom welcome
- message. This can be used in various ways:
-
- mqmsg "1 2 3 4 5"
- ifeq @mail 0
- fprint @usernum.bbs "You had no mail waiting at @time on @date."
- else
- ifgt @mail 2
- fprint @usernum.bbs "You've got a lot of mail waiting. It must"
- fprint @usernum.bbs "be nice to be so popular. Please delete some"
- fprint @usernum.bbs "after reading."
- endif
- endif
-
- I don't recommend leaving custom welcome messages to users without waiting mail
- unless you've got disk space to burn, or a very small cluster size.
-
- Examples: MQMSG "1 2 3 4 5"
-
- See also: CWKILL, DOS, FAPPEND, FPRINT, MQFLUSH
-
-
-
- 3.4.15 MUL variable numerical_expression
-
- Multiplies the value in 'variable' by the value of 'numerical_expression'.
- If 'numerical_expression' is null (""), its value is considered to be 0, and
- 'variable' gets set to 0.
-
- Examples: MUL @VAR0 10
-
- See also: ADD, SUB, DIV, MOD, SET
-
-
- 3.4.16 NEXTUSER
-
- Causes UPL to immediately proceed to processing the next user in the
- USER.BBS file. This will also restart the current program from the top. If
- you remember that your UPL program is assumed to be within a FOR USERNUM=0 TO
- LASTUSER loop, you can see that NEXTUSER simply jumps to the NEXT USERNUM
- statement which is assumed to follow your program. An identical effect could
- be achieved by placing a label at the end of your program and jumping there
- with GOTO, but NEXTUSER is faster.
-
- See also: ABORT, CHAIN, END, RUN
-
-
- 3.4.17 RUN
-
- Causes UPL to stop reading and parsing commands, and to execute the program
- which it has read so far. This command allows you to have more than one
- executable UPL program within a single command file. Once this program has
- finished, UPL will resume reading and parsing commands from the command file
- starting with the line after the RUN command. Each program separated by a RUN
- command is a totally separate entity; the only communication possible between
- them is via the user-defined variables (@VAR0 - @VAR9), which maintain their
- current values from one program to the next.
-
- See also: ABORT, CHAIN, END, NEXTUSER
-
-
- 3.4.18 SET variable expression
-
- Sets the contents of 'variable' to the value of 'expression'. UPL will
- attempt to convert the data type of 'expression' to that of 'variable' if
- possible. A string variable may be set to anything, and will be truncated if
- too long. An integer may be set to any value from -32768 to 32767. An
- unsigned variable may be set to any value from 0 to 65535. A byte may be set
- to any numeric value, but only the least significant 8 bits of the expression
- will be used (0-255). A bit may be set to any numeric value, but any value
- other than 0 will be treated as 1. If you attempt to do something silly like
- set an integer variable to an alphabetic string, a fatal error will be
- generated. The special user-data derived variables @DAYSAGO, @ULRATIO, and
- @USERNUM can not be directly set (but you could set @LASTCALL, or @DOWNLOADS,
- or whatever).
-
- Examples: SET @PRIV @TWIT
- SET @VAR0 "This is a text string"
- SET @VAR0 12
- SET @PASSWORD ""
-
- See also: ADD, SUB, MUL, DIV, MOD
-
-
-
-
- 3.4.19 SUB variable numeric_expression
-
- Subtracts the value of 'numerical_expression' from 'variable'. If
- 'numerical_expression' is null (""), its value is considered to be 0, and
- nothing happens.
-
- Examples: SUB @VAR0 1
- SUB @CREDIT @DEBIT (hopefully followed by SET @DEBIT 0)
-
- See also: ADD, MUL, DIV, MOD, SET
-
-
- 3.4.20 PRINT textline_expression
-
- Prints the value of 'textline_expression' on the console. Embedded control
- codes and carriage-return suppression are available; see section 3.3 for
- details on textline expressions.
-
- Examples: Print "Are you as tired of reading this as I am of typing it?"
- print "Last read #@MRC@VAR0 in area @MRA@VAR0."
-
-
- 3.4.21 PURGE
-
- This command will read through your USER.BBS file and remove any user data
- records which have been flagged as deleted. There are two deletion flags
- supported. The first one, @DELFLG1, is the least significant bit of @FLAGWORD
- (@FLAGBIT0). This bit is used by SYSOP207 and some other sysop maintainence
- programs as a flag to remember which records have been marked for deletion. The
- second one, @DELFLG2, is stored as a text string within the field reserved for
- the user's city and state. This is the method used by REMSYSOP. Note that
- although the flag is stored in the record as a text string, UPL treats @DELFLG2
- as a bit variable. If you set @DELFLG2 to 0, the text string will be nulled
- out; if you set @DELFLG2 to 1, the text string will be inserted.
-
- UPL will rename your current USER.BBS file as USER.BAK before doing the
- purge. Then your old user data is read, and each record is written to either
- the new USER.BBS file, or to USER.OLD. USER.BAK and USER.OLD are deleted if
- neccessary before purging. When the purge is completed, the PURGE command will
- execute an implied END command, since UPL no longer knows what your USER.BBS
- file looks like.
-
- See also: END
-
-
-
- 4.0 Programming Considerations
- --------------------------------
-
- 4.1 Limitations.
-
- There are several arbitrary limits to a UPL program. I have tried to set
- these higher than anyone should ever need:
-
- Maximum number of executable commands per program: 1024
- (ELSE and ENDIF also count, as they have tokens
- kept there for trace mode outputs)
-
- Maximum nesting depth for IF statements: 100
-
- Maximum number of labels per program: 100
-
- Maximum number of expressions per program: 900+ (depends)
-
- When I say 'per program,' I mean per each individually executed program within
- a command file, NOT per command file as a whole. If you manage to run into any
- of these limits, let me know; I'd like to know what you're doing to my poor
- interpreter while I'm not watching.
-
-
- 4.2 Efficiency considerations.
-
- UPL is a one-pass tokenizing interpreter. It reads and tokenizes commands
- from the command file until either a RUN command or the end of file is
- encountered. It then opens your USER.BBS file and performs the tokenized
- commands in a loop for each record in your user data file.
-
- Constants are evaluated during the tokenization process, and so are
- basically free. Using a constant is exactly like typing in that literal text
- manually. Variables, on the other hand, are evaluated as the commands which
- use them are executed, every time they are executed. A complex expression can
- require quite a bit of time to evaluate. This is the easiest way to slow down
- your UPL programs. Also, GOTO's are slower than ELSE's, so try to write
- reasonably structured top-down code if possible. It's quite possible for more
- code to be faster than less code... for example:
-
- set @var0 0
-
- NextArea:
- ifeq @mra@var0 @arg1
- set @mra@var0 @arg2
- print 'Changed area @arg1 to area @arg2 for @name.'
- else
- add @var0 1
- ifle @var0 9
- goto NextArea
- endif
- endif
-
- This is a slick little routine to change every occurrence of a given last
- message read area (@ARG1) to a new area number (@ARG2). This would be used if
- you move a message area to somewhere else, and feel like being nice to your
- users. Note the cute way in which the 10 different area numbers are checked in
- a loop by incrementing @VAR0. However, the following program does the same
- thing, faster, since it doesn't have to evaluate that cute little '@MRA@VAR0'
- trick, or do that GOTO:
-
-
-
-
- ifeq @mra0 @arg1
- set @mra0 @arg2
- print 'Changed area @arg1 to area @arg2 for @name.'
- nextuser
- else
- ifeq @mra1 @arg1
- set @mra1 @arg2
- print 'Changed area @arg1 to area @arg2 for @name.'
- nextuser
- else
- ifeq @mra2 @arg1
- set @mra2 @arg2
- print 'Changed area @arg1 to area @arg2 for @name.'
- nextuser
- else
- ifeq @mra3 @arg1
- set @mra3 @arg2
- print 'Changed area @arg1 to area @arg2 for @name.'
- nextuser
- else
- ifeq @mra4 @arg1
- set @mra4 @arg2
- print 'Changed area @arg1 to area @arg2 for @name.'
- nextuser
- else
- ifeq @mra5 @arg1
- set @mra5 @arg2
- print 'Changed area @arg1 to area @arg2 for @name.'
- nextuser
- else
- ifeq @mra6 @arg1
- set @mra6 @arg2
- print 'Changed area @arg1 to area @arg2 for @name.'
- nextuser
- else
- ifeq @mra7 @arg1
- set @mra7 @arg2
- print 'Changed area @arg1 to area @arg2 for @name.'
- nextuser
- else
- ifeq @mra8 @arg1
- set @mra8 @arg2
- print 'Changed area @arg1 to area @arg2 for @name.'
- nextuser
- else
- ifeq @mra9 @arg1
- set @mra9 @arg2
- print 'Changed area @arg1 to area @arg2 for @name.'
- endif
- nextuser
- endif
- endif
- endif
- endif
- endif
- endif
- endif
- endif
- endif
-
-
-
-
- Note that although not strictly neccessary, the NEXTUSER commands speed
- things up a little bit by saving UPL the trouble of falling through all those
- ELSE's and ENDIFs (Yes, ELSE and ENDIF do take a teeny bit of time, since UPL
- has to check if you've got trace mode on, but not as much as a GOTO).
-
- One last word on efficiency... I'll admit right now that UPL was written in
- QuickBasic, not 'C'. I know full well that if I had written it in C it would
- be half the size and go twice as fast. However, since I don't own a commercial
- quality C compiler and source level debugger, it would have taken me twice as
- long to write, and would probably never have gotten finished. Maybe I'll redo
- it once Turbo C gets released, but don't hold your breath.
-
-
-
-
- 5.0 Postscript
- ----------------
-
- 5.1 Future Enhancements.
-
- The only future enhancement which I'm definately going to make is support of
- whatever new Opus user data structure Wynn finally settles on. As a matter of
- fact, the next major rev of UPL will probably not be usable on Fido systems
- anymore at all (but they can keep using version 1).
-
- I will make an effort to fix any bugs which are discovered, and I'm willing
- to listen to ideas for enhancements. I'm not promising to implement them all,
- just to listen to them.
-
-
- 5.2 Bug Reports, etc.
-
- Send any bug reports or enhancement requests to me at my board,
- FidoNet/Matrix node 14/614 (402-291-8053 3/12/2400 bps, 24 hrs.). Constructive
- criticism, heaps of praise, expensive 'C' compilers, and lucrative job offers
- will be cheerfully accepted. Snide comments and hate mail will convince me
- never to bother writing utilities for anyone else again.
-
- A copy of the latest version of this program will always be available on my
- board for download by first-time callers. I don't run SEADog, so don't bother
- file requesting it.
-
-
-
- END
-
-